package com.service.lotterySystem.service.impl;

import com.service.config.utils.IdUtil;
import com.service.config.utils.Result;
import com.service.lotterySystem.dao.*;
import com.service.lotterySystem.dto.*;
import com.service.config.utils.DateUtils;
import com.service.config.utils.IdUtil;
import com.service.config.utils.ModelMapperUtil;
import com.service.config.utils.Result;
import com.service.config.utils.StringUtils;
import com.service.lotterySystem.dto.LogisticsInfoDto;
import com.service.lotterySystem.dto.UploadPrizeDto;
import com.service.lotterySystem.dto.UserDto;
import com.service.lotterySystem.entity.*;
import com.service.lotterySystem.dao.LogisticsInfoDao;
import com.service.lotterySystem.service.LogisticsInfoService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;

import static com.service.config.constant.Constant.*;
import static com.service.config.constant.Constant.DATA_FORMAT_WRONG;

/**
 * 物流编号表(支持上传excel)logistics_info）(LogisticsInfo)表服务实现类
 *
 * @author makejava
 * @since 2022-01-19 09:04:30
 */
@Service("logisticsInfoService")
@Slf4j
public class LogisticsInfoServiceImpl implements LogisticsInfoService {
    private static final Logger LOG = LoggerFactory.getLogger(LogisticsInfoServiceImpl.class);

    @Resource
    private LogisticsInfoDao logisticsInfoDao;
    @Resource
    private PrizeServiceImpl prizeService;
    @Resource
    private ActivityInfoDao activityInfoDao;
    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private ReceiveAddressDao addressDao;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public LogisticsInfo queryById(String id) {
        return this.logisticsInfoDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<LogisticsInfo> queryAllByLimit(int offset, int limit) {
        return this.logisticsInfoDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param logisticsInfo 实例对象
     * @return 实例对象
     */
    @Override
    public LogisticsInfo insert(LogisticsInfo logisticsInfo) {
        this.logisticsInfoDao.insert(logisticsInfo);
        return logisticsInfo;
    }

    /**
     * 修改数据
     *
     * @param logisticsInfo 实例对象
     * @return 实例对象
     */
    @Override
    public LogisticsInfo update(LogisticsInfo logisticsInfo) {
        this.logisticsInfoDao.update(logisticsInfo);
        return this.queryById(logisticsInfo.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(String id) {
        return this.logisticsInfoDao.deleteById(id) > 0;
    }

    @Override
    public Result addLogisticsInfoByExcel(MultipartFile file, String aid, UserDto userDto) throws Exception {
        ActivityInfo activityInfo = activityInfoDao.queryById(aid);
        if (null == activityInfo)
        {
            return Result.failure(PARAMETER_NOT_FOUND,"未查询到该活动信息");
        }
        // 1.判断文件是否为空
        if (file == null) {
            return Result.failure(UPLOAD_EXCEL_EMPTY, UPLOAD_EXCEL_EMPTY_INFO);
        }
        // 2.判断上传内容是否符合要求
        String fileName = file.getOriginalFilename();
        // 判断是否是excel文件
        if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
            return Result.failure(UPLOAD_EXCEL_ERROR, UPLOAD_EXCEL_ERROR_INFO);
        }
        //获取Excel表格数据
        List<UploadLogisticsInfoDto> uploadLogisticsInfoDtos = prizeService.batchImport(file, UploadLogisticsInfoDto.class,1);
        if(null==uploadLogisticsInfoDtos)
        {
            return Result.failure(FILE_ISNULL,"当前文件无数据");
        }

        UserInfo userInfo = new UserInfo();
        List<UserInfo> userInfos = userInfoDao.queryAll(userInfo);
        ReceiveAddress address=new ReceiveAddress();
        List<ReceiveAddress> addressList = addressDao.queryAll(address);
        //校验Excel数据
        Map<Integer, String> result = checkExcelData(uploadLogisticsInfoDtos,activityInfo,userInfos,addressList);
        //数据有异常,返回错误信息
        if(result.containsKey(0))
        {
            return Result.failure(DATA_FORMAT_WRONG,result.get(0));
        }

        //上传物流信息
        List<LogisticsInfo> uploadLogisticsInfo= new ArrayList<>();
        List<LogisticsInfo> logisticsInfos = logisticsInfoDao.queryAllLogicsticsOfActivity(aid);
        uploadLogisticsInfoDtos.forEach(uploadLogisticsInfoDto -> {
            boolean flag = logisticsInfos.stream().filter(logisticsInfo2 -> logisticsInfo2.getAId().equals(uploadLogisticsInfoDto.getAId()) && logisticsInfo2.getUId().equals(uploadLogisticsInfoDto.getUId())).findAny().isPresent();
            //若上传的某活动的用户数据在数据库表中已经存在，则修改；反之新增
            if (false == flag)
            {
                //新增物流单号
                LogisticsInfo logisticsInfo = ModelMapperUtil.strictMap(uploadLogisticsInfoDto, LogisticsInfo.class);
                if (logisticsInfo.getLNum() !=null && !logisticsInfo.getLNum().equals(""))
                {
                    logisticsInfo.setId(IdUtil.getStringId());
                    logisticsInfo.setLUploadTime(DateUtils.getNowDate());
                    logisticsInfo.setOperateId(userDto.getId());
                    uploadLogisticsInfo.add(logisticsInfo);
                }
            }else {
                if (uploadLogisticsInfoDto.getLNum() != null && !uploadLogisticsInfoDto.getLNum().equals(""))
                {
                    //修改物流单号
                    Optional<LogisticsInfo> logisticsOp = logisticsInfos.stream().filter(logisticsInfo2 -> logisticsInfo2.getAId().equals(uploadLogisticsInfoDto.getAId()) && logisticsInfo2.getUId().equals(uploadLogisticsInfoDto.getUId())).findAny();
                    if (logisticsOp.isPresent())
                    {
                        LogisticsInfo logisticsInfo1 = logisticsOp.get();
                        logisticsInfo1.setLNum(uploadLogisticsInfoDto.getLNum());
                        logisticsInfo1.setLUploadTime(DateUtils.getNowDate());
                        logisticsInfo1.setOperateId(userDto.getId());
                        uploadLogisticsInfo.add(logisticsInfo1);
                    }
                }
            }

        });
        //批量上传
        if (uploadLogisticsInfo!=null && uploadLogisticsInfo.size()>0)
        {
            LOG.info(uploadLogisticsInfo.toString());
            logisticsInfoDao.insertOrUpdateBatch(uploadLogisticsInfo);
        }

        return Result.ok();
    }

    @Override
    public Result addLogisticsInfo(AddLogisticsInfoDto addLogisticsInfoDto,String operateId) {
        String id = IdUtil.getStringId();
        LogisticsInfo logisticsInfo = ModelMapperUtil.strictMap(addLogisticsInfoDto, LogisticsInfo.class);
        logisticsInfo.setId(id);
        logisticsInfo.setLUploadTime(DateUtils.getNowDate());
        logisticsInfo.setOperateId(operateId);
        logisticsInfoDao.insert(logisticsInfo);
        return Result.ok().setData(id);
    }

    @Override
    public Result queryLogisticsInfo(UserDto userDto, Integer card,String aId) {
        ActivityInfo activityInfo = activityInfoDao.queryById(aId);
        if (activityInfo.getAType() ==1 || activityInfo.getAType() ==2) {
            Result.failure("活动还在进行中.....");
        }
        if (card == 1) { // 运营
            List<LogisticsInfoDto> logisticsInfoDtos = logisticsInfoDao.queryLogisticsInfoByUserId("", aId, "", null);
            logisticsInfoDtos.stream().forEach(logisticsInfoDto -> {
                logisticsInfoDto.setTelphone(StringUtils.getStarString(logisticsInfoDtos.get(0).getTelphone(),3, 7));
            });
            return Result.ok().setData(logisticsInfoDtos);
        }
        if (card == 0) { // 用户
            List<LogisticsInfoDto> logisticsInfoDtos = logisticsInfoDao.queryLogisticsInfoByUserId(userDto.getId(), aId, "", null);
            if (logisticsInfoDtos.size() > 0) {
                String Uname = StringUtils.getStarString(logisticsInfoDtos.get(0).getTelphone(), 3, 7);
                logisticsInfoDtos.get(0).setTelphone(Uname);
                return Result.ok().setData(logisticsInfoDtos.get(0));
            }
            Result.failure("物流单号暂未录入,请耐心等待");
        }
        return Result.failure("物流单号暂未录入,请耐心等待");
    }

    @Override
    public Result updateLogisticsInfo(LogisticsInfoDto logisticsInfoDto,String operateId) {
        LogisticsInfo logisticsInfo = ModelMapperUtil.strictMap(logisticsInfoDto, LogisticsInfo.class);
        logisticsInfo.setLUploadTime(DateUtils.getNowDate());
        logisticsInfo.setOperateId(operateId);
        logisticsInfoDao.update(logisticsInfo);
        return Result.ok();
    }

    public Map<Integer,String> checkExcelData(List<UploadLogisticsInfoDto> uploadLogisticsInfoDtos,ActivityInfo activityInfo,List<UserInfo> userInfos,List<ReceiveAddress> addressList)
    {
        Map<Integer,String> map=new HashMap<>();
        for (int i=0;i<uploadLogisticsInfoDtos.size();i++)
        {
            if (uploadLogisticsInfoDtos.get(i).getTel()==null || uploadLogisticsInfoDtos.get(i).getTel().equals(""))
            {
                map.put(0,"第"+(i+1)+1+"行账号信息有误");
                return map;
            }
            if (uploadLogisticsInfoDtos.get(i).getAId()==null || uploadLogisticsInfoDtos.get(i).getAId().equals("") || !uploadLogisticsInfoDtos.get(i).getAId().equals(activityInfo.getId()))
            {
                map.put(0,"第"+(i+1)+"行活动id格式有误或与上传活动不符");
                return map;
            }
            if (uploadLogisticsInfoDtos.get(i).getAName()==null || uploadLogisticsInfoDtos.get(i).getAName().equals("") || !uploadLogisticsInfoDtos.get(i).getAName().equals(activityInfo.getAName()))
            {
                map.put(0,"第"+(i+1)+"行活动名称格式有误或与上传活动不符");
                return map;
            }

            String uId = uploadLogisticsInfoDtos.get(i).getUId();
            Optional<UserInfo> opUser = userInfos.stream().filter(userInfo ->
                    userInfo.getId().equals(uId)
            ).findAny();
            if (opUser.isPresent())
            {
                UserInfo user = opUser.get();
                if (user == null)
                {
                    map.put(0,"第"+(i+1)+"行用户id格式有误");
                    return map;
                }
                if (!user.getNickName().equals(user.getNickName()))
                {
                    map.put(0,"第"+(i+1)+"行用户昵称格式有误");
                    return map;
                }
            }
        }
        return map;
    }
}
